`:top
`!PureScript`! est un `F33f`_`[langage de programmation`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Langage_de_programmation]`_`f `F33f`_`[fonctionnel`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Programmation_fonctionnelle]`_`f `F33f`_`[fortement typé`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Typage_fort]`_`f dont la compilation produit du code `F33f`_`[JavaScript`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=JavaScript]`_`f. Il peut être utilisé pour développer des `F33f`_`[applications web`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Application_web]`_`f, des applications serveur, et également des applications de bureau grâce au `F33f`_`[framework`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Framework]`_`f `F33f`_`[Electron`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Electron_(framework)]`_`f. Sa syntaxe est pour l'essentiel comparable à celle d'`F33f`_`[Haskell`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Haskell]`_`f. Cependant, le langage introduit un `F33f`_`[polymorphisme paramétré`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Polymorphisme_(informatique)]`_`f particulier lié aux enregistrements extensibles`:cite-ref-3[`F5bf`_`[3`#cite-note-3]`_`f] : les enregistrements polymorphes (en). De plus, contrairement à Haskell, PureScript adhère à une `F33f`_`[stratégie d'évaluation`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Stratégie_d'évaluation_(informatique)]`_`f stricte.
>>Contents
• `F0af`_`[Historique`#historique]`_`f
• `F0af`_`[Caractéristiques`#caract-ristiques]`_`f
• `F0af`_`[Exemples de codes`#exemples-de-codes]`_`f
• `F0af`_`[Enregistrements en PureScript`#enregistrements-en-purescript]`_`f
• `F0af`_`[Enregistrements polymorphes`#enregistrements-polymorphes]`_`f
• `F0af`_`[Extensibilité des prototypes`#extensibilit-des-prototypes]`_`f
• `F0af`_`[Système de types`#syst-me-de-types]`_`f
• `F0af`_`[Voir aussi`#voir-aussi]`_`f
• `F0af`_`[Notes et références`#notes-et-r-f-rences]`_`f
• `F0af`_`[Liens externes`#liens-externes]`_`f
-─
>>Historique
PureScript fut initialement conçu par Phil Freeman en 2013. Celui-ci entama son travail sur PureScript après différentes tentatives insatisfaisantes de compilations d'Haskell vers JavaScript préservant sa sémantique (en utilisant par exemple Fay, Haste, ou GHCJS)`:cite-ref-4[`F5bf`_`[4`#cite-note-4]`_`f].
Depuis, le projet a été repris par la communauté et est développé sur `F33f`_`[GitHub`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=GitHub]`_`f`:cite-ref-5[`F5bf`_`[5`#cite-note-5]`_`f]. Parmi les outils essentiels additionnels développés par la communauté, on peut citer l'outil dédié de compilation "Pulp"`:cite-ref-6[`F5bf`_`[6`#cite-note-6]`_`f], le site documentaire "Pursuit"`:cite-ref-7[`F5bf`_`[7`#cite-note-7]`_`f], et le gestionnaire de packages "Spago"`:cite-ref-8[`F5bf`_`[8`#cite-note-8]`_`f]
>>Caractéristiques
PureScript se fonde sur l'`F33f`_`[évaluation stricte`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Évaluation_stricte]`_`f, la `F33f`_`[structure de données persistante`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Structure_de_données_persistante]`_`f et l'`F33f`_`[inférence de types`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Inférence_de_types]`_`f. Le `F33f`_`[système de types`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Théorie_des_types]`_`f de PureScript partage de nombreuses caractéristiques avec celui de langages fonctionnels similaires comme `F33f`_`[Haskell`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Haskell]`_`f: les `F33f`_`[types algébriques de données`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Type_algébrique_de_données]`_`f et le `F33f`_`[filtrage par motif`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Filtrage_par_motif]`_`f, les "higher kinded types" (en), les "type classes" (en) et les `F33f`_`[dépendances fonctionnelles`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Type_dépendant]`_`f, ainsi que le polymorphisme "higher-rank" (en). Le système de types de PureScript assure également les enregistrements polymorphes (en) et les `F33f`_`[enregistrements extensibles`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Hugs]`_`f`:cite-ref-docu-9-0[`F5bf`_`[9`#cite-note-docu-9]`_`f]. Toutefois, PureScript ne possède pas certaines des caractéristiques les plus avancées d'Haskell comme les `F33f`_`[GADT`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Type_algébrique_de_données]`_`f et les "type families" (en).
Le `F33f`_`[compilateur`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Compilateur]`_`f de PureScript tend à produire du code JavaScript lisible, autant que possible. Grâce à une simple interface "FFI" (en) il permet l'intégration de code JavaScript existant`:cite-ref-docu-9-1[`F5bf`_`[9`#cite-note-docu-9]`_`f].
PureScript assure la `F33f`_`[compilation incrémentale`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Compilation_incrémentale]`_`f, et la distribution inclut un support au développement intéractif à partir de plugins à installer dans l'`F33f`_`[éditeur de code source`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Éditeur_de_texte]`_`f`:cite-ref-10[`F5bf`_`[10`#cite-note-10]`_`f]. Des plugins existent pour un grand nombre d'éditeurs connus incluant `F33f`_`[Vim`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Vim]`_`f, `F33f`_`[Emacs`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Emacs]`_`f, `F33f`_`[Sublime Text`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Sublime_Text]`_`f, `F33f`_`[Atom`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Atom_(éditeur_de_texte)]`_`f et `F33f`_`[Visual Studio Code`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Visual_Studio_Code]`_`f.
>>Exemples de codes
Voici un programme `F33f`_`["Hello world!"`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Hello_World]`_`f minimal en PureScript:
`B100`F9d9module Main where`f`b
`B100`F9d9`f`b
`B100`F9d9import Effect.Console (log)`f`b
`B100`F9d9`f`b
`B100`F9d9main = log "Hello World!"`f`b
Ici, le type du programme est inféré et vérifié par le compilateur PureScript. Une version plus verbeuse du même programme pourrait explicitement inclure des annotations de type:
`B100`F9d9module Main where`f`b
`B100`F9d9`f`b
`B100`F9d9import Prelude`f`b
`B100`F9d9`f`b
`B100`F9d9import Effect (Effect)`f`b
`B100`F9d9import Effect.Console (log)`f`b
`B100`F9d9`f`b
`B100`F9d9main :: Effect Unit`f`b
`B100`F9d9main = log "Hello World!"`f`b
>>>Enregistrements en PureScript
Le modèle choisi pour développer les enregistrements en PureScript a permis l'accès à certaines fonctionnalités qui sont encore absentes d'Haskell`:cite-ref-11[`F5bf`_`[11`#cite-note-11]`_`f], ce qui fait de lui l'une des caractéristiques majeures du langage.
En tout premier lieu, il faut préciser qu'en PureScript chaque enregistrement possède un type particulier réservé à cet usage, qui est lui-même présenté sous la forme d'un enregistrement composé par un ensemble (non ordonné) de couples \`étiquette :: type\`.
Ainsi
`B100`F9d9carré :: { côté :: Number, aire :: Number }`f`b
`B100`F9d9carré = { côté: 3.0, aire: 9.0 }`f`b
et
`B100`F9d9disque :: { rayon :: Number, aire :: Number }`f`b
`B100`F9d9disque = { rayon: 1.0, aire: 3.141592653589793 }`f`b
sont deux enregistrements de types différents car, bien que le nombre et le type des valeurs sont les mêmes, les étiquettes ne le sont pas.
>>>Enregistrements polymorphes
Il est toutefois possible de définir une fonction qui peut s'appliquer à chacun des enregistrements précédents grâce au concept d'enregistrement polymorphe:
`B100`F9d9aireDe :: forall r. { aire :: Number | r } -> Number`f`b
`B100`F9d9aireDe = _.aire`f`b
où le type de l'argument peut se lire comme "le type de tout enregistrement qui possède une étiquette \`aire\` de type \`Number\`, et qui possède éventuellement d'autre(s) étiquette(s)". L'argument de cette fonction est donc un enregistrement polymorphe et le compilateur aurait inféré
`B100`F9d9aireDe :: forall a b. { aire :: a | b } -> a`f`b
si l'annotation n'avait pas été précisée.
>>>Extensibilité des prototypes
En réalité, la notation { étiquette1 :: Type1, étiquette2 :: Type2 } n'est qu'un `F33f`_`[sucre syntaxique`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Sucre_syntaxique]`_`f d'une construction plus générale qui facilite l'extension des types d'`F33f`_`[enregistrements`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Type_algébrique_de_données]`_`f, `B100`F9d9Record`f`b en PureScript (l'extension des `F33f`_`[unions disjointes étiquetées`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Type_algébrique_de_données]`_`f`:cite-ref-12[`F5bf`_`[12`#cite-note-12]`_`f] est similaire). Cette construction est réalisée à partir de déclarations, de juxtapositions et d'applications de prototypes (`B100`F9d9Row`f`b):
`B100`F9d9-- Prototypes (syntaxe commune aux enregistrements et aux variants):`f`b
`B100`F9d9type NonConcrétisableA r = ( aire :: Number | r )`f`b
`B100`F9d9type NonConcrétisableBC r = ( boîte :: Boolean, côté :: Number | r )`f`b
`B100`F9d9type NonConcrétisableABC r = NonConcrétisableA (NonConcrétisableBC r)`f`b
Il n'est pas directement possible de créer des valeurs correspondant à ces prototypes (`B100`F9d9Row Type`f`b et `B100`F9d9Type`f`b ne sont pas dans la même `F33f`_`[catégorie`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Théorie_des_catégories]`_`f). Pour ce faire, on utilise le constructeur `B100`F9d9Record`f`b:
`B100`F9d9-- Type concret et ouvert (= paramétré):`f`b
`B100`F9d9type Enregistrement r = Record (NonConcrétisableABC r)`f`b
Des valeurs peuvent alors peupler ce type:
`B100`F9d9-- Type concret et fermé (= non-paramétré):`f`b
`B100`F9d9carré :: Enregistrement ()`f`b
`B100`F9d9carré =`f`b
`B100`F9d9 { côté: 2.0`f`b
`B100`F9d9 , aire: 4.0`f`b
`B100`F9d9 , boîte: false`f`b
`B100`F9d9 }`f`b
ou une de ses extensions:
`B100`F9d9-- Type concret, étendu et fermé:`f`b
`B100`F9d9cube :: Enregistrement (volume :: Number)`f`b
`B100`F9d9cube =`f`b
`B100`F9d9 { côté: 2.0`f`b
`B100`F9d9 , aire: 24.0`f`b
`B100`F9d9 , volume: 8.0`f`b
`B100`F9d9 , boîte: true`f`b
`B100`F9d9 }`f`b
>>>Système de types
La similitude assumée entre le système de types d'Haskell et celui de PureScript comporte néanmoins certaines nuances, tant au niveau de la syntaxe (par exemple, le "genre" (en) `B100`F9d9*`f`b d'Haskell se nomme `B100`F9d9Type`f`b en PureScript), qu'aux niveaux des contraintes liées à sa manipulation (aucune extension n'est nécessaire pour accéder à la programmation au niveau "types" en PureScript) et des applications (la programmation au niveau "types" est nécessaire dans certains cas.)
En guise d'illustration sont présentés comparativement ci-après deux programmes PureScript complets qui, tous deux,
• définissent le couplage générique entre deux entiers,
• définissent l'égalité entre deux couples d'entiers, et
• constatent la non-égalité de deux couples particuliers d'entiers,
mais, tandis que l'un est écrit dans un style de programmtion au niveau "valeurs" (connues au moment de l'exécution du programme), l'autre est écrit dans le style de programmation de niveau "types" (déterminés dès l'étape de compilation du programme) qui s'apparente à la `F33f`_`[programmation logique`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Programmation_logique]`_`f.
De plus, tandis que le premier programme manipule des entiers (signés) en simple précision (`B100`F9d9Int`f`b), le second utilise des entiers en `F33f`_`[multiprécision`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Arithmétique_multiprécision]`_`f (`B100`F9d9Int`f`b également, le contexte permettant la distinction), car l'usage de ce genre d'entiers nécessite la programmation de niveau "types" en PureScript si on se limite aux bibliothèques pré-installées.
`t
| Code au niveau valeurs | Description au niveau valeurs | | Code au niveau types | Description au niveau types |
|---|---|---|---|---|
| module Main where | | | module Main where | |
| import Prelude ( Unit , ( == ) , ( && ) , ( $ ) , show ) import Effect ( Effect ) import Effect.Console ( log ) | l.5: comparaison d'entiers incluse | | import Prelude ( Unit , ( $ ) ) import Data.Symbol ( reflectSymbol , class IsSymbol ) import Effect ( Effect ) import Effect.Console ( log ) import Prim.Boolean ( True , False ) import Prim.Int ( class Compare ) import Prim.Ordering ( Ordering , EQ ) import Type.Prelude ( Proxy ( .. ) ) | l.22 : comparaison d'entiers incluse Les éléments de Prim font référence à la programmation de niveau "types". |
| data SimpleCouple :: Type data SimpleCouple = S Int Int | l.20: S , le constructeur de type est employé directement pour décrire comment créer une nouvelle valeur possédant le type SimpleCouple Int est ici le type des entiers codés sur 32 bits | | data MultiCouple :: Type data MultiCouple foreign import data M :: Int -> Int -> MultiCouple | l.36: M , le constructeur de type est indirectement décrit et aucun moyen pour construire une valeur de type MultiCouple n'est fourni l.37 et 38: Int est ici le type des entiers en précision arbitraire |
| class EgalitéV :: Type -> Constraint class EgalitéV v where égalitéV :: v -> v -> Boolean | l.22: la logique de ce programme tient entre les lignes 36 et 40; la classe, ici, est facultative et ne serait utile que si d'autres types possédaient la propriété EgalitéV l.30: Boolean est le booléen des valeurs, ses habitants sont true et false | | class EgalitéT :: MultiCouple -> MultiCouple -> Boolean -> Constraint class EgalitéT m1 m2 b / m1 m2 -> b class Subordonnée :: Ordering -> Ordering -> Boolean -> Constraint class Subordonnée compart comparu résultat / compart comparu -> résultat | l.41 à 48: première étape essentielle de la mise en place de la logique du programme, cette partie fait état des entrées ( m1 et m2 ) et sortie ( b ) du comportement fonctionnel que l'on implémente l.44 et 53: Boolean est le booléen des types, ses habitants sont True et False |
| instance EgalitéV SimpleCouple where égalitéV ( S v1 w1 ) ( S v2 w2 ) = v1 == v2 && w1 == w2 | | | instance Subordonnée EQ EQ True else instance Subordonnée c1 c2 False instance ( Compare t1 t2 compart , Compare u1 u2 comparu , Subordonnée compart comparu résultat ) => EgalitéT ( M t1 u1 ) ( M t2 u2 ) résultat | l.74 à 91: cette seconde étape constitue le cœur du problème et est résolu durant la phase de compilation |
| rendu :: Boolean -> String rendu = show | | | class Symbolise :: Boolean -> Symbol -> Constraint class Symbolise b s / b -> s instance Symbolise True "True" instance Symbolise False "False" rendu :: forall s . IsSymbol s => Proxy s -> String rendu = reflectSymbol | l.97 à 106: fonctionnalité auxiliaire permettant ultérieurement d'utiliser la fonction reflectSymbol |
| aprèsExécution :: Boolean aprèsExécution = égalitéV ( S 3 4 ) ( S 5 6 ) | l.51 et 52: 3, 4, 5 et 6 sont considérés en simple précision | | aprèsCompilation :: forall b s . EgalitéT ( M 3 4 ) ( M 5 6 ) b => Symbolise b s => Proxy s aprèsCompilation = Proxy | l.118 et 119: 3, 4, 5 et 6 sont considérés en multiprécision l.122: derrière le type Proxy s se cache le résultat de la résolution du problème l.124: c'est l'identifiant Proxy qui a été choisi pour représenter toute valeur de type Proxy s pour tout s |
| main :: Effect Unit main = log $ rendu aprèsExécution | | | main :: Effect Unit main = log $ rendu aprèsCompilation | |
`t
>>Voir aussi
• `F33f`_`[Elm`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=Elm_(langage)]`_`f
• `F33f`_`[TypeScript`:/page/wikibook/entry.mu`zim=wikipedia_fr_all_nopic_2025-10.zim|entry_path=TypeScript]`_`f
>>Notes et références
`:cite-note-wikidata-611c4fdf413f9c91c7b9c14257205dbbc7c6d2ef-1`!1.`! « Release 0.15.15 », 7 février 2024 (consulté le 20 février 2024)
`:cite-note-license-2`!2.`! « purescript/purescript », sur GitHub
`:cite-note-3`!3.`! `F0af`_`[↑`#cite-ref-3]`_`f « Hugs documentation », sur www.haskell.org
`:cite-note-4`!4.`! `F0af`_`[↑`#cite-ref-4]`_`f « Read PureScript by Example | Leanpub », sur leanpub.com (consulté le 14 mars 2019)
`:cite-note-5`!5.`! `F0af`_`[↑`#cite-ref-5]`_`f « PureScript on Github »
`:cite-note-6`!6.`! `F0af`_`[↑`#cite-ref-6]`_`f « Pulp », PureScript Contrib (consulté le 14 mars 2019)
`:cite-note-7`!7.`! `F0af`_`[↑`#cite-ref-7]`_`f « Pursuit », sur pursuit.purescript.org (consulté le 14 mars 2019)
`:cite-note-8`!8.`! `F0af`_`[↑`#cite-ref-8]`_`f `:2019`a« 🍝 PureScript package manager and build tool powered by Dhall and package-sets: spacchetti/spago », spacchetti, 14 mars 2019 (consulté le 14 mars 2019)
`:cite-note-docu-9`!9.`! `:2019`a« Documentation for the PureScript language, compiler, and tools.: purescript/documentation », PureScript, 14 mars 2019 (consulté le 14 mars 2019)
`:cite-note-10`!10.`! `F0af`_`[↑`#cite-ref-10]`_`f `:2019`a« purs ide: Editor and tooling support for the PureScript programming language », 21 avril 2019 (consulté le 21 avril 2019)
`:cite-note-11`!11.`! `F0af`_`[↑`#cite-ref-11]`_`f « Extensible record », sur wiki.haskell.org
`:cite-note-12`!12.`! `F0af`_`[↑`#cite-ref-12]`_`f `:2019`a« `B100`F9d9Variant`f`b », 21 avril 2019 (consulté le 21 avril 2019)
>>Liens externes
• www.purescript.org
• Portail de la programmation informatique
`c`F0af`_`[↑ Back to top`#top]`_`f`a